//go:build mage
// +build mage

package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/magefile/mage/mg"
	"github.com/magefile/mage/sh"
)

const (
	appName = "domain-system"
	pidFile = "domain-system.pid"
	logFile = "domain-system.log"
)

// getBinaryName 根据平台返回二进制文件名
func getBinaryName() string {
	if runtime.GOOS == "windows" {
		return "domain-system.exe"
	}
	return "domain-system"
}

// Default target to run when none is specified
var Default = Build

// Build 编译项目
func Build() error {
	fmt.Println("🔨 编译项目...")
	binaryName := getBinaryName()
	return sh.Run("go", "build", "-ldflags=-s -w", "-o", binaryName, ".")
}

// Clean 清理编译文件
func Clean() error {
	fmt.Println("🧹 清理编译文件...")
	binaryName := getBinaryName()
	files := []string{binaryName, pidFile, logFile, "coverage.out", "coverage.html"}
	for _, file := range files {
		if _, err := os.Stat(file); err == nil {
			if err := os.Remove(file); err != nil {
				fmt.Printf("警告: 无法删除文件 %s: %v\n", file, err)
			} else {
				fmt.Printf("✅ 已删除: %s\n", file)
			}
		}
	}
	return nil
}

// Test 运行测试
func Test() error {
	fmt.Println("🧪 运行测试...")
	return sh.Run("go", "test", "./tests/...", "-v")
}

// TestCover 运行测试并生成覆盖率报告
func TestCover() error {
	fmt.Println("📊 运行测试并生成覆盖率报告...")
	if err := sh.Run("go", "test", "./tests/...", "-coverprofile=coverage.out"); err != nil {
		return err
	}
	return sh.Run("go", "tool", "cover", "-html=coverage.out", "-o", "coverage.html")
}

// Start 启动服务（后台运行）
func Start() error {
	fmt.Println("🚀 启动服务...")

	// 检查是否已经在运行
	if isRunning() {
		fmt.Println("⚠️  服务已经在运行中")
		return nil
	}

	binaryName := getBinaryName()
	// 确保二进制文件存在
	if _, err := os.Stat(binaryName); os.IsNotExist(err) {
		fmt.Println("📦 二进制文件不存在，正在编译...")
		if err := Build(); err != nil {
			return fmt.Errorf("编译失败: %v", err)
		}
	}

	// 获取可执行文件的完整路径
	execPath, err := getExecutablePath(binaryName)
	if err != nil {
		return fmt.Errorf("获取可执行文件路径失败: %v", err)
	}

	// 启动服务
	cmd := exec.Command(execPath)

	// 创建日志文件
	logfile, err := os.Create(logFile)
	if err != nil {
		return fmt.Errorf("创建日志文件失败: %v", err)
	}
	defer logfile.Close()

	cmd.Stdout = logfile
	cmd.Stderr = logfile

	// 启动进程
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("启动服务失败: %v", err)
	}

	// 保存PID
	pid := cmd.Process.Pid
	if err := savePID(pid); err != nil {
		return fmt.Errorf("保存PID失败: %v", err)
	}

	fmt.Printf("✅ 服务已启动，PID: %d\n", pid)
	fmt.Printf("📝 日志文件: %s\n", logFile)

	return nil
}

// getExecutablePath 获取可执行文件的完整路径
func getExecutablePath(binaryName string) (string, error) {
	if runtime.GOOS == "windows" {
		// Windows上使用完整路径
		wd, err := os.Getwd()
		if err != nil {
			return "", err
		}
		return filepath.Join(wd, binaryName), nil
	} else {
		// Unix系统使用相对路径
		return "./" + binaryName, nil
	}
}

// Stop 停止服务
func Stop() error {
	fmt.Println("🛑 停止服务...")

	pid, err := readPID()
	if err != nil {
		fmt.Println("⚠️  服务未运行或PID文件不存在")
		return nil
	}

	// 跨平台停止进程
	if err := stopProcess(pid); err != nil {
		return fmt.Errorf("停止进程失败: %v", err)
	}

	// 删除PID文件
	os.Remove(pidFile)

	fmt.Printf("✅ 服务已停止，PID: %d\n", pid)
	return nil
}

// Restart 重启服务
func Restart() error {
	fmt.Println("🔄 重启服务...")

	if isRunning() {
		if err := Stop(); err != nil {
			return err
		}
		// 等待一秒确保进程完全停止
		time.Sleep(1 * time.Second)
	}

	return Start()
}

// Status 查看服务状态
func Status() error {
	fmt.Println("📊 服务状态:")

	if !isRunning() {
		fmt.Println("❌ 服务未运行")
		return nil
	}

	pid, err := readPID()
	if err != nil {
		fmt.Println("❌ 无法读取PID文件")
		return nil
	}

	fmt.Printf("✅ 服务正在运行，PID: %d\n", pid)

	// 显示日志文件信息
	if info, err := os.Stat(logFile); err == nil {
		fmt.Printf("📝 日志文件: %s (大小: %d bytes, 修改时间: %s)\n",
			logFile, info.Size(), info.ModTime().Format("2006-01-02 15:04:05"))
	}

	return nil
}

// Logs 查看日志
func Logs() error {
	fmt.Println("📝 查看日志...")

	if _, err := os.Stat(logFile); os.IsNotExist(err) {
		fmt.Println("❌ 日志文件不存在")
		return nil
	}

	// 显示最后50行日志
	if runtime.GOOS == "windows" {
		return sh.Run("powershell", "Get-Content", logFile, "-Tail", "50")
	} else {
		return sh.Run("tail", "-n", "50", logFile)
	}
}

// Dev 开发模式运行（前台运行，实时重载）
func Dev() error {
	fmt.Println("🔧 开发模式启动...")
	return sh.Run("go", "run", "main.go")
}

// Install 安装mage依赖
func Install() error {
	fmt.Println("📦 安装依赖...")
	if err := sh.Run("go", "mod", "download"); err != nil {
		return err
	}
	return sh.Run("go", "mod", "tidy")
}

// Deploy 部署到生产环境
func Deploy() error {
	fmt.Println("🚀 部署到生产环境...")

	// 清理
	mg.Deps(Clean)

	// 编译
	if err := Build(); err != nil {
		return err
	}

	// 运行测试
	if err := Test(); err != nil {
		return fmt.Errorf("测试失败，停止部署: %v", err)
	}

	// 重启服务
	return Restart()
}

// 辅助函数

// isRunning 检查服务是否正在运行
func isRunning() bool {
	pid, err := readPID()
	if err != nil {
		return false
	}

	return isProcessRunning(pid)
}

// isProcessRunning 跨平台检查进程是否运行
func isProcessRunning(pid int) bool {
	if runtime.GOOS == "windows" {
		// Windows上使用tasklist检查进程
		cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid))
		output, err := cmd.Output()
		if err != nil {
			return false
		}
		return strings.Contains(string(output), fmt.Sprintf("%d", pid))
	} else {
		// Unix系统使用ps检查进程
		cmd := exec.Command("ps", "-p", fmt.Sprintf("%d", pid))
		err := cmd.Run()
		return err == nil
	}
}

// stopProcess 跨平台停止进程
func stopProcess(pid int) error {
	if runtime.GOOS == "windows" {
		// Windows使用taskkill
		return exec.Command("taskkill", "/F", "/PID", fmt.Sprintf("%d", pid)).Run()
	} else {
		// Unix系统使用kill
		return exec.Command("kill", "-TERM", fmt.Sprintf("%d", pid)).Run()
	}
}

// readPID 读取PID文件
func readPID() (int, error) {
	data, err := os.ReadFile(pidFile)
	if err != nil {
		return 0, err
	}

	pidStr := strings.TrimSpace(string(data))
	return strconv.Atoi(pidStr)
}

// savePID 保存PID到文件
func savePID(pid int) error {
	return os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644)
}
